#include "include/state_manager.h"

namespace codec {
void StateManager::setDataSource(int fd) {
  currentState->setDataSource(playManager_.get(), fd);
  transitionTo(PlayerStateCode::INITIALIZED);
};
void StateManager::prepare(ANativeWindow *window, const std::string &vertexCode,
                           const std::string &fragmentCode) {
  auto result = currentState->prepare(playManager_.get(), window, vertexCode,
                                      fragmentCode);
  transitionTo(PlayerStateCode::PREPARED, result);
}
void StateManager::start() {
  currentState->start(playManager_.get());
  playManager_->registerProgressCallback([&](double progross, double duration) {
    if (progross < 1) {
      auto result = std::map<std::string, std::string>();
      result["progross"] = std::to_string(progross);
      result["duration"] = std::to_string(duration);
      if (currentState->getCode() == PlayerStateCode::SEEKING) {
        transitionTo(PlayerStateCode::PLAYING);
      }
      notifyStateChange(PlayerStateCode::PLAYING, result);
    } else {
      transitionTo(PlayerStateCode::COMPLETED);
    }
  });
  transitionTo(PlayerStateCode::PLAYING);
}
void StateManager::seekTo(float position) {
  currentState->seekTo(playManager_.get(), position);
  transitionTo(PlayerStateCode::SEEKING);
}

void StateManager::pause() {
  currentState->pause(playManager_.get());
  transitionTo(PlayerStateCode::PAUSED);
}

void StateManager::resume() {
  currentState->resume(playManager_.get());
  transitionTo(PlayerStateCode::PLAYING);
}

void StateManager::release() {
  playManager_->unregisterProgressCallback();
  playManager_->release();
  transitionTo(PlayerStateCode::IDLE);
}

void StateManager::transitionTo(PlayerStateCode newState,
                                const std::map<std::string, std::string> &map) {
  if (isValidTransition(currentState->getCode(), newState)) {
    switch (newState) {
      case PlayerStateCode::IDLE:
        currentState = std::make_unique<IdleState>();
        break;
      case PlayerStateCode::INITIALIZED:
        currentState = std::make_unique<InitializedState>();
        break;
      case PlayerStateCode::PREPARED:
        currentState = std::make_unique<PreparedState>();
        break;
      case PlayerStateCode::PLAYING:
        currentState = std::make_unique<PlayingState>();
        break;
      case PlayerStateCode::PAUSED:
        currentState = std::make_unique<PausedState>();
        break;
      case PlayerStateCode::STOPPED:
        currentState = std::make_unique<StopState>();
        break;
      case PlayerStateCode::SEEKING:
        currentState = std::make_unique<SeekingState>();
        break;
      case PlayerStateCode::ERROR:
        currentState = std::make_unique<ErrorState>();
        break;
      case PlayerStateCode::COMPLETED:
        currentState = std::make_unique<CompletedState>();
        break;

      default:
        break;
    }
    notifyStateChange(newState, map);
  } else {
  }
}
void StateManager::transitionTo(PlayerStateCode newState) {
  if (isValidTransition(currentState->getCode(), newState)) {
    auto map = std::map<std::string, std::string>();
    switch (newState) {
      case PlayerStateCode::IDLE:
        currentState = std::make_unique<IdleState>();
        break;
      case PlayerStateCode::INITIALIZED:
        currentState = std::make_unique<InitializedState>();
        break;
      case PlayerStateCode::PREPARED:
        currentState = std::make_unique<PreparedState>();
        break;
      case PlayerStateCode::PLAYING:
        currentState = std::make_unique<PlayingState>();
        break;
      case PlayerStateCode::PAUSED:
        currentState = std::make_unique<PausedState>();
        break;
      case PlayerStateCode::STOPPED:
        currentState = std::make_unique<StopState>();
        break;
      case PlayerStateCode::SEEKING:
        currentState = std::make_unique<SeekingState>();
        break;
      case PlayerStateCode::ERROR:
        currentState = std::make_unique<ErrorState>();
        break;
      case PlayerStateCode::COMPLETED:
        currentState = std::make_unique<CompletedState>();
        break;

      default:
        break;
    }
    notifyStateChange(newState, map);
  } else {
  }
}
bool StateManager::isValidTransition(PlayerStateCode oldState,
                                     PlayerStateCode newState) {
  __android_log_print(ANDROID_LOG_INFO, "StateManager",
                      "oldState%d,newState:%d", oldState, newState);
  return true;
}

void StateManager::setCallback(CallbackType callback) { callback_ = callback; }

void StateManager::notifyStateChange(
    PlayerStateCode code, const std::map<std::string, std::string> &map) {
  if (callback_ != nullptr) {
    callback_(code, map);
  }
}

}  // namespace codec